import * as vscode from 'vscode';
import { HiLogService, LogLevel } from './HiLogService';

export class HiLogViewProvider implements vscode.WebviewViewProvider {
    public static readonly viewType = 'hiLogView';
    private webviewView?: vscode.WebviewView;
    private disposables: vscode.Disposable[] = [];
    private hiLogService: HiLogService;

    constructor(private readonly _extensionUri: vscode.Uri) {
        this.hiLogService = HiLogService.getInstance();
    }

    resolveWebviewView(
        webviewView: vscode.WebviewView,
        context: vscode.WebviewViewResolveContext,
        _token: vscode.CancellationToken
    ) {

        this.webviewView = webviewView;

        // Configure webview
        webviewView.webview.options = {
            enableScripts: true,
            localResourceRoots: [vscode.Uri.joinPath(this._extensionUri, 'webview-ui', 'dist')]
        };

        // Initial HTML content
        webviewView.webview.html = this.getHtmlForWebview(webviewView.webview);

        // Set up message handling
        this.setupMessageHandling(webviewView);

        // Subscribe to log updates from HiLogService
        const logUpdateDisposable = this.hiLogService.onLogUpdate((log) => {
            if (this.webviewView) {
                this.webviewView.webview.postMessage({ 
                    command: 'addLogs', 
                    logs: log 
                });
            }
        });

        // Subscribe to device disconnection notifications
        const deviceDisconnectedDisposable = this.hiLogService.onDeviceDisconnected(() => {
            if (this.webviewView) {
                this.webviewView.webview.postMessage({
                    command: 'deviceDisconnected'
                });
            }
        });

        // Start device monitoring
        // this.hiLogService.startDeviceMonitoring();

        // Store disposables
        this.disposables.push(
            logUpdateDisposable,
            deviceDisconnectedDisposable,
            webviewView.onDidDispose(() => {
                // Clean up when the webview is closed
                this.disposables.forEach(d => d.dispose());
                this.disposables = [];
            })
        );

        // 监听主题变化
        vscode.window.onDidChangeActiveColorTheme((theme) => {
            const isDark = theme.kind === vscode.ColorThemeKind.Dark;
            webviewView.webview.postMessage({
                messageType: "themeChange",
                data: {
                    isDark,
                },
            });
        });
    }

    private setupMessageHandling(webviewView: vscode.WebviewView) {
        webviewView.webview.onDidReceiveMessage(
            async message => {
                switch (message.command) {
                    case 'showHiLog':
                        vscode.commands.executeCommand('hiLogView.focus');
                        break;
                    case 'clearLogs':
                        this.hiLogService.clearLogBuffer();
                        break;
                    case 'changeLogLevel':
                        // 处理日志级别变更
                        const newLevel = message.level as LogLevel;
                        if (Object.values(LogLevel).includes(newLevel)) {
                            await this.hiLogService.setLogLevel(newLevel);
                            // 清空日志缓冲区以避免混淆不同级别的日志
                            this.hiLogService.clearLogBuffer();
                            // 通知WebView日志级别已更改
                            if (this.webviewView) {
                                this.webviewView.webview.postMessage({
                                    command: 'logLevelChanged',
                                    level: newLevel
                                });
                            }
                        }
                        break;
                    case 'getDeviceList':
                        // 处理获取设备列表请求
                        this.sendDeviceList();
                        break;
                    case 'getProcessList':
                        // 处理获取进程列表请求
                        this.sendProcessList(message.device);
                        break;
                    case 'queryLogs':
                        // 处理查询日志请求
                        await this.handleQueryLogs(message);
                        break;
                    case 'saveLogs':
                        // 处理保存日志请求
                        this.handleSaveLogs(message.enable);
                        break;
                }
            },
            undefined,
            this.disposables
        );
    }

    // 发送设备列表到 webview
    private sendDeviceList() {
        // 这里我们通过HiLogService获取实际连接的设备
        // 为简化示例，可以先使用模拟数据
        this.hiLogService.getConnectedDevices().then(devices => {
            if (this.webviewView) {
                this.webviewView.webview.postMessage({
                    command: 'deviceList',
                    devices: devices
                });
            }
        }).catch(error => {
            // 出错时发送空列表
            if (this.webviewView) {
                this.webviewView.webview.postMessage({
                    command: 'deviceList',
                    devices: []
                });
            }
            console.error('Failed to get device list:', error);
        });
    }

    // 发送进程列表到 webview
    private sendProcessList(deviceId: string) {
        if (!deviceId) {
            this.sendErrorMessage('未指定目标设备');
            return;
        }

        this.hiLogService.getProcessList(deviceId).then(processes => {
            if (this.webviewView) {
                this.webviewView.webview.postMessage({
                    command: 'processList',
                    processes: processes
                });
            }
        }).catch(error => {
            // 出错时发送空列表
            if (this.webviewView) {
                this.webviewView.webview.postMessage({
                    command: 'processList',
                    processes: []
                });
            }
            console.error('Failed to get process list:', error);
            this.sendErrorMessage('获取进程列表失败');
        });
    }

    // 发送错误消息到 webview
    private sendErrorMessage(message: string) {
        if (this.webviewView) {
            this.webviewView.webview.postMessage({
                command: 'error',
                message: message
            });
        }
    }

    // 处理查询日志请求
    private async handleQueryLogs(message: any) {
        const { device, process, logLevel, searchKey } = message;
        
        // 检查设备是否指定
        if (!device) {
            this.sendErrorMessage('未指定目标设备');
            return;
        }
        
        // 通知HiLogService设置日志过滤条件
        if (device) {
            this.hiLogService.setTargetDevice(device);
        }
        
        if (logLevel) {
            // 将前端日志级别字符串转换为LogLevel枚举
            let level: LogLevel;
            switch (logLevel) {
                case 'DEBUG':
                    level = LogLevel.DEBUG;
                    break;
                case 'INFO':
                    level = LogLevel.INFO;
                    break;
                case 'WARN':
                    level = LogLevel.WARN;
                    break;
                case 'ERROR':
                    level = LogLevel.ERROR;
                    break;
                case 'FATAL':
                    level = LogLevel.FATAL;
                    break;
                case 'ALL':
                    level = LogLevel.ALL;
                    break;
                default:
                    level = LogLevel.INFO;
            }
            await this.hiLogService.setLogLevel(level);
        }
        
        if (process) {
            this.hiLogService.setProcessFilter(process);
        }
        
        if (searchKey) {
            this.hiLogService.setSearchKeyword(searchKey);
        }
        
        // 清空当前日志并重新开始监控
        this.hiLogService.clearLogBuffer();
        await this.hiLogService.restartLogMonitoring();
    }

    // 处理保存日志请求
    private handleSaveLogs(enable: boolean) {
        this.hiLogService.enableLogSaving(enable);
    }

    private getNonce() {
		let result = '';
		const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
		const charactersLength = characters.length;
		for (let i = 0; i < 32; i++) {
			result += characters.charAt(Math.floor(Math.random() * charactersLength));
		}
		return result;
	}
    private getHtmlForWebview(webview: vscode.Webview) {
		// Get the local path to main script run in the webview
		const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'webview-ui', 'dist', 'assets', 'index.js'));
		
		// Get the local path to css styles
		const styleUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, 'webview-ui', 'dist', 'assets', 'index.css'));
		
		// Use a nonce to only allow specific scripts to be run
		const nonce = this.getNonce();
        // 初始主题状态
        const isDark = vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark;
		return `<!DOCTYPE html>
			<html lang="en" class="${isDark ? 'dark' : ''}">
			<head>
				<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width, initial-scale=1.0">
				<title>HiLog</title>
				<link href="${styleUri}" rel="stylesheet">
				<script nonce="${nonce}">
					// Set initial route for the Vue app
					window.initialRoute = '#/hilog';
					// Setup VSCode API access
					const vscode = acquireVsCodeApi();
					window.vscode = vscode;
				</script>
			</head>
			<body>
				<div id="app"></div>
				<script type="module" nonce="${nonce}" src="${scriptUri}"></script>
                <script>
                    window.addEventListener('message', e => {
                        if (e.data.messageType === 'themeChange') {
                            document.documentElement.classList.toggle('dark', e.data.data.isDark);
                        }
                        
                    });
                </script>
			</body>
			</html>`;
	}
}